//
//  XDFS.m
//  XDFS
//
//  Created by Yury Soldak on 30/09/2008.
//

#import "XDFS.h"
#import "XDModel.h"

@interface XDFS (Private)
- (NSString*) filenameForHref:(NSString*) href;
@end

@implementation XDFS

static NSString* const kUrlFileTemplate = @"[InternetShortcut]\nURL=%@\n";
static int const kMaxItemsWithoutSubtags = 10;
static BOOL const kExcludeTagsWithSameItems = NO; // remove all (except first) folders which have same items in them

# pragma mark Init and Dealloc Methods

- (id) initWithModel:(XDModel*) input {
	if (self = [super init]) {
		model = [input retain];
	}
	return self;
}

- (void) dealloc {
	[model release];
	[super dealloc];
}

#pragma mark Main Logic Methods

- (NSSet*) filterTags:(NSSet*) tags withCurrentTags:(NSSet*) current {
	NSMutableSet* result = [NSMutableSet setWithSet:tags];
	NSMutableSet* tagsArray1 = [NSMutableSet setWithSet:current];
	NSMutableSet* tagsArray2 = [NSMutableSet setWithSet:current];
	for (NSString* tag1 in tags) {
		[tagsArray1 addObject:tag1];
		NSSet* hrefs1 = [model hrefsForTags:tagsArray1];
		for (NSString* tag2 in tags) {
			if ([tag1 isEqualToString:tag2] || ![result containsObject:tag2])
				continue;
			[tagsArray2 addObject:tag2];
			NSSet* hrefs2 = [model hrefsForTags:tagsArray2];
			//if ([hrefs2 isSubsetOfSet:hrefs1] || (kExcludeTagsWithSameItems && [hrefs2 isEqualToSet:hrefs1]) ) {
			if ([hrefs2 isSubsetOfSet:hrefs1]) {
				[result removeObject:tag2];
			}
			[tagsArray2 removeObject:tag2];
		}
		[tagsArray1 removeObject:tag1];
	}
	return result;
}

- (NSSet*) topLevelDirectories {
	return [self filterTags:[model allTags] withCurrentTags:[NSArray array]];
}

- (NSSet*) itemsForPath:(NSString*) path {
	NSMutableSet* result = [NSMutableSet set];

	NSMutableSet* currentTags = [NSMutableSet setWithArray:[path pathComponents]];
	[currentTags removeObject:@"/"];
	
	NSSet* hrefs = [model hrefsForTags:currentTags];
	
	if ([hrefs count] > kMaxItemsWithoutSubtags) {
		NSMutableSet* tagsToAdd = [NSMutableSet set];
		for (NSString* href in hrefs) {
			NSSet* tags = [model tagsForHref:href];
			[tagsToAdd unionSet:tags];
			if ([tags count] == [currentTags count]) { // add item if it is tagged only with current tags
				[result addObject:[self filenameForHref:href]];
			}
		}
		[tagsToAdd minusSet:currentTags];
		[result unionSet:[self filterTags:tagsToAdd withCurrentTags:currentTags]];
	} else {
		for (NSString* href in hrefs) {
			[result addObject:[self filenameForHref:href]];
		}
	}
	
	return result;
}

#pragma mark Overridden GMUserFileSystem Delegate Methods

- (NSArray*) contentsOfDirectoryAtPath:(NSString*) path error:(NSError**) error {
	NSString* lastComponent = [path lastPathComponent];
	if ([lastComponent isEqualToString:@"/"]) {
		return [[self topLevelDirectories] allObjects];
	} else {
		return [[self itemsForPath:path] allObjects];
	}
}

- (NSDictionary*) attributesOfItemAtPath:(NSString*) path error:(NSError**)error {
	NSString* ext = [path pathExtension];
	BOOL isDirectory = ![ext isEqualToString:@"url"];
	int mode = 0500;
	
	NSMutableDictionary *attr = nil;
	attr = [NSDictionary dictionaryWithObjectsAndKeys:
			[NSNumber numberWithInt:mode], NSFilePosixPermissions,
			[NSNumber numberWithInt:geteuid()], NSFileOwnerAccountID,
			[NSNumber numberWithInt:getegid()], NSFileGroupOwnerAccountID,
			[NSDate date], NSFileCreationDate,
			[NSDate date], NSFileModificationDate,
			(isDirectory ? NSFileTypeDirectory : NSFileTypeRegular), NSFileType,
			nil];
	return attr;
}

- (NSData*) contentsAtPath:(NSString*) path {
	NSString* fileName = [path lastPathComponent];
	NSString* name = [fileName substringToIndex:([fileName length] - 4)]; // strip ".url"
	NSString* href = [model hrefForName:name];
	NSMutableString* data = [NSMutableString stringWithFormat:kUrlFileTemplate, href];
	return [data dataUsingEncoding:NSUTF8StringEncoding];
}


@end

@implementation XDFS (Private)
- (NSString*) filenameForHref:(NSString*) href {
	return [NSMutableString stringWithFormat:@"%@.url", [model nameForHref:href]];
}
@end

